package com.eatme.web.app.coupon.template.service.impl;

import com.eatme.web.WebCaseApplication;
import com.eatme.web.app.coupon.common.constant.Constant;
import com.eatme.web.app.coupon.template.dao.CouponTemplateDao;
import com.eatme.web.app.coupon.template.entity.CouponTemplate;
import com.eatme.web.app.coupon.template.service.IAsyncService;
import com.google.common.base.Stopwatch;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 异步服务接口实现
 */
@Service
public class AsyncServiceImpl implements IAsyncService {

    /** couponTemplateDao */
    @Autowired
    private CouponTemplateDao couponTemplateDao;

    /* 注入Redis 模板类 */
    @Autowired
    private StringRedisTemplate redisTemplate;

    private static final Logger LOG = LoggerFactory.getLogger(WebCaseApplication.class);

    @Async("getAsyncExecutor")
    @Override
    public void asyncConstructCouponByTemplate(CouponTemplate template) {
        Stopwatch watch = Stopwatch.createStarted();
        Set<String> couponCodes = buildCouponCode(template);

        String redisKey = String.format("%s%S",Constant.RedisPrefix.COUPON_TEMPLATE,template.getId().toString());
        LOG.info("Push CouponCode To Redis: {}",redisTemplate.opsForList().rightPushAll(redisKey,couponCodes));
        template.setAvailable(true);
        couponTemplateDao.save(template);

        watch.stop();
        LOG.info("Construct CouponCode By Template Cost: {}ms",watch.elapsed(TimeUnit.MILLISECONDS));

        // TODO 发送短信或者邮件优惠券模板已经可用
        LOG.info("CouponTemplate({}) Is Available!",template.getId());

    }

    /**
     * 构造优惠券码
     * 优惠券码(对应于每一张优惠券,18位)
     * 前四位: 产品线 + 类型
     * 中间六位: 日期随机(230301)
     * @param template {@link CouponTemplate} 实体类
     * @return Set<String> 与 template.count 相同个数的优惠券码
     */
    private Set<String> buildCouponCode(CouponTemplate template) {

        Stopwatch watch = Stopwatch.createStarted();
        Set<String> result = new HashSet<>(template.getCount());

        // 前线四位的生成
        String prefix4 = template.getProductLine().getCode().toString()
                +template.getCategory().getCode();
        String date = new SimpleDateFormat("yyMMdd").format(template.getCreateTime());
        for (int i = 0; i < template.getCount(); ++i) {
            result.add(prefix4+buildCouponCodeSuffix14(date));
        }

        while (result.size()<template.getCount()) {
            result.add(prefix4+buildCouponCodeSuffix14(date));
        }
        assert result.size() == template.getCount();

        watch.stop();
        LOG.info("Build Coupon Code Cost: {}ms",watch.elapsed(TimeUnit.MILLISECONDS));

        return result;
    }

    /**
     * 构造优惠券码的后 14位
     * @param date 创建优惠券的日期
     * @return 14 位优惠券
     */
    private String buildCouponCodeSuffix14(String date) {
        char[] bases = new char[]{'1','2','3','4','5','6','7','8','9'};

        // 中间六位
        List<Character> chars = date.chars()
                .mapToObj(e -> (char) e).collect(Collectors.toList());
        Collections.shuffle(chars);
        String mid6 = chars.stream().map(Objects::toString).collect(Collectors.joining());

        // 后八位
        String suffix8 = RandomStringUtils.random(1,bases)
                + RandomStringUtils.randomNumeric(7);
        return mid6+ suffix8;
    }


}
